package com.easymin.weixin.controller.h5.v4;

import com.google.common.base.Preconditions;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.easymin.weixin.common.Distance;
import com.easymin.weixin.common.WxUtils;
import com.easymin.weixin.common.api.DaijiaApi;
import com.easymin.weixin.common.api.ErrandApi;
import com.easymin.weixin.common.api.PassengerApi;
import com.easymin.weixin.entity.Order;
import com.easymin.weixin.entity.OrderType;
import com.easymin.weixin.entity.WxAccount;
import com.easymin.weixin.entity.WxApplication;
import com.easymin.weixin.entity.passenger.Passenger;
import com.easymin.weixin.manager.ErrandManager;
import com.easymin.weixin.manager.WxAccountManager;
import com.easymin.weixin.manager.WxApplicationManager;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by shine on 16/1/4.
 */
@RestController
@RequestMapping("h5/v4/pt")
public class PaotuiV4Controller {
  
  private static final Logger logger = LoggerFactory.getLogger(PaotuiV4Controller.class);

  private static final String WX_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";

  private static final String WX_JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={access_token}&type=jsapi";

  @Autowired
  private DaijiaApi daijiaApi;

  @Autowired
  private PassengerApi passengerApi;

  @Autowired
  private ErrandApi errandApi;

  @Autowired
  private ErrandManager errandManager;

  @Autowired
  private WxApplicationManager wxApplicationManager;

  @Autowired
  private WxAccountManager wxAccountManager;

  @Autowired
  private RestTemplate restTemplate;

  /**
   * 查询跑腿类型.
   * @param appkey 系统key
   * @param ack 区分公司
   * @param lat 纬度
   * @param lng 经度
   * @param passengerId 客户id
   * @return List
   */
  @RequestMapping("getServiceTypes")
  public List<OrderType> getServiceTypes(
      @RequestParam("appkey") String appkey,
      @RequestParam(required = false, value = "ack") String ack,
      @RequestParam("lat") Double lat,
      @RequestParam("lng") Double lng,
      @RequestParam(required = false, value = "passengerId") Long passengerId) {
    
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appkey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    Long companyId = null;

    if(StringUtils.isBlank(ack)){
      Long passengerCompanyId = null;
      if (passengerId != null) {
        Passenger passenger = passengerApi.findById(passengerId, appkey);
        if (null != passenger) {
          passengerCompanyId = passenger.getCompanyId();
        }
      }
      JSONObject compay = daijiaApi.getCompany(
          wxApplication.getAddress(), appkey, passengerCompanyId, lng, lat);

      companyId = compay.getLong("data");
    }else{
      JSONObject compay = daijiaApi.getCompanyIdAndName(wxApplication.getAddress(), ack, null, lng, lat);
      JSONObject jsonObject2 = compay.getJSONObject("data");
      companyId = jsonObject2.getLong("companyId");
    }
    

    return errandManager.findByCompanyId(companyId, appkey);
  }

  /**
   * 查询未完成订单.
   * @param appkey 系统key
   * @param passengerId 客户id
   * @return JSONArray
   */
  @RequestMapping("getRunning")
  public JSONArray getRunning(
      @RequestParam("appkey") String appkey, @RequestParam("passengerId") Long passengerId) {

    WxApplication wxApplication = wxApplicationManager.findByAppKey(appkey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return errandApi.findRunning(passengerId, appkey);
  }


  /**
   * 查询附近的司机人数,默认距离为5公里.
   * @param appKey 系统key
   * @param companyId 公司id
   * @param lat 纬度
   * @param lng 经度
   * @return JSONObject
   */
  @RequestMapping("countNearEmploys")
  public JSONObject countNearEmploys(
      @RequestParam("appkey") String appKey,
      @RequestParam("companyId") Long companyId,
      @RequestParam("lat") Double lat,
      @RequestParam("lng") Double lng) {
    
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    JSONObject jsonObject = daijiaApi.queryErrandDriver(
        wxApplication.getAddress(), companyId, 5.0, lng, lat);

    JSONObject result = new JSONObject();
    result.put("count", 0);

    if (jsonObject.getIntValue("code") == 0) {
      JSONArray jsonArray = jsonObject.getJSONArray("data");
      int size = jsonArray.size();
      if (size > 0) {
        if (companyId != null && companyId != 0) {
          String distanceStr = "";

          DecimalFormat df = new DecimalFormat("#.00");

          Double distance = 0.0;

          for (int i = 0; i < size; i++) {
            JSONObject jo = jsonArray.getJSONObject(i);
            if (i == 0) {
              distance = Distance.doubleVal(
                  lat, lng, jo.getDoubleValue("driverLat"), jo.getDoubleValue("driverLng"));
            } else {
              Double dou = Distance.doubleVal(
                  lat, lng, jo.getDoubleValue("driverLat"), jo.getDoubleValue("driverLng"));
              if (distance > dou) {
                distance = dou;
                distance = Double.valueOf(df.format(distance));
              }
            }
            if (distance >= 1) {
              distanceStr = df.format(distance) + "公里";
            } else {
              distanceStr = (long) (distance * 1000) + "米";
            }
          }
          result.put("distance", distanceStr);
        } else {
          JSONObject perfect = null;
          for (int i = 0; i < size; i++) {
            JSONObject jo = jsonArray.getJSONObject(i);
            if (i == 0) {
              perfect = jo;
              continue;
            }
            if (perfect.getDoubleValue("distance") > jo.getDoubleValue("distance")) {
              perfect = jo;
            }
          }
          result.put("distance", perfect.getString("distanceStr"));
        }
        result.put("count", size);
      }
    }

    return result;
  }

  /**
   * 预算费用.
   * @param appKey 系统key
   * @param areaId 收费id
   * @param startLat 开始纬度
   * @param startLng 开始经度
   * @param endLat 结束纬度
   * @param endLng 结束经度
   * @return Map
   */
  @RequestMapping("calculationPrice")
  public Map<String, Object> calculationPrice(
      @RequestParam("appkey") String appKey,
      @RequestParam("areaId") Long areaId,
      @RequestParam("startLat") Double startLat,
      @RequestParam("startLng") Double startLng,
      @RequestParam(required=false, value = "endLat") Double endLat,
      @RequestParam(required=false, value = "endLng") Double endLng) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return daijiaApi.getPriceByAreaId(
        wxApplication.getAddress(), areaId, startLat, startLng, endLat, endLng);

  }

  /**
   * 预约订单.
   * @param appKey 系统key
   * @param phone 手机号
   * @param typeId 类型id
   * @param content 内容
   * @param startAddress 开始地址
   * @param startLat 开始纬度
   * @param startLng 开始经度
   * @param shouldPay 支付金额
   * @param travelTime 预算总时间
   * @param mileage 总公里数
   * @param startPrice 开始价
   * @param mileagePrice 里程价格
   * @param travelTimePrice 时间价格
   * @param deliverAddress 收货地址
   * @param deliverLat 收货纬度
   * @param deliverLng 收货经度
   * @param openId 微信id
   * @return Object
   */
  @RequestMapping(value = "makeAnAppointment", method = RequestMethod.POST)
  public Object makeAnAppointment(
      @RequestParam("appkey") String appKey,
      @RequestParam("phone") String phone,
      @RequestParam("typeId") Long typeId,
      @RequestParam("content") String content,
      @RequestParam("startAddress") String startAddress,
      @RequestParam("startLat") Double startLat,
      @RequestParam("startLng") Double startLng,
      @RequestParam("shouldPay") Double shouldPay,
      @RequestParam("travelTime") Integer travelTime,
      @RequestParam("mileage") Double mileage,
      @RequestParam("startPrice") Double startPrice,
      @RequestParam("mileagePrice") Double mileagePrice,
      @RequestParam("travelTimePrice") Double travelTimePrice,
      @RequestParam(required = false, value = "deliverAddress") String deliverAddress,
      @RequestParam(required = false, value = "deliverLat") Double deliverLat,
      @RequestParam(required = false, value = "deliverLng") Double deliverLng,
      @RequestParam(required = false, value = "openId") String openId) throws Exception {

    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    String channelName = "网站预约";

    if (org.apache.commons.lang3.StringUtils.isNotBlank(openId)) {
      channelName = "微信预约";
    }

    Passenger passenger = passengerApi.findOne(phone, appKey);

    return errandManager.saveWeixinOrder(passenger.getId(), passenger.getName(),
        passenger.getPhone(), startAddress, startLat, startLng, deliverAddress, deliverLat,
        deliverLng, startPrice, mileagePrice, travelTimePrice, mileage, travelTime, shouldPay,
        typeId, content, appKey, channelName, wxApplication.getAddress());
  }

  /**
   * 查询单个订单.
   */
  @RequestMapping("findOrder")
  public Order findOrder(
      @RequestParam("appkey") String appkey,
      @RequestParam("orderId") Long orderId) throws Exception {

    WxApplication wxApplication = wxApplicationManager.findByAppKey(appkey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return errandManager.findOne(orderId, appkey);

  }

  /**
   * 取消订单.
   * @param appkey 系统key
   * @param orderId 订单id
   * @param reson 销单理由
   * @return JSONObject
   */
  @RequestMapping(value = "cancelOrder", method = RequestMethod.POST)
  public JSONObject cancelOrder(
      @RequestParam("appkey") String appkey,
      @RequestParam("orderId") Long orderId,
      @RequestParam(required=true, value="reson") String reson) throws Exception {

    WxApplication wxApplication = wxApplicationManager.findByAppKey(appkey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    Order order = errandManager.findOne(orderId, appkey);
    JSONObject result = new JSONObject();
    result.put("success", true);
    try {
      errandManager.updateStatusV2(
          orderId, null, null, null, null, "cancel", order.getPassengerName(), reson, appkey);
    } catch (Exception ex) {
      logger.error(ex.getMessage());
      result.put("success", false);
      result.put("message", "该订单已经完成或者已经销单");
    }

    return result;
  }

  /**
   * 微信支付.
   * @param appKey 系统key
   * @param orderId 订单id
   * @param openid 微信id
   * @param appid 微信应用id
   * @param request 判断是否来自微信
   * @return JSONObject
   */
  @RequestMapping(value = "doPayForWx", method = RequestMethod.POST)
  public JSONObject doPayForWx(
      @RequestParam("appkey") String appKey, 
      @RequestParam("orderId") Long orderId,
      @RequestParam("openid") String openid,
      @RequestParam("appid") String appid, 
      HttpServletRequest request) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    WxAccount wxAccount = wxAccountManager.findBy(appid, wxApplication.getId());
    Preconditions.checkArgument(null != wxAccount, "appid错误");

    //判断是否来自微信
    StringBuilder sb = new StringBuilder();
    sb.append(request.getScheme());
    sb.append("://");
    sb.append(request.getServerName());
    int port = request.getServerPort();
    if (port != 80) {
      sb.append(":").append(port);
    }
    sb.append(request.getRequestURI());
    String queryString = request.getQueryString();
    if (StringUtils.isNotBlank(queryString)) {
      sb.append("?");
      sb.append(queryString);
    }

    JSONObject jsonObject = new JSONObject();

    JSONObject jo = daijiaApi.getPtWxPrepayId(wxApplication.getAddress(), orderId, openid);
    jsonObject.put("package", jo.getString("package"));
    jsonObject.put("timestamp", jo.getString("timeStamp"));
    jsonObject.put("url", sb.toString());
    jsonObject.put("nonceStr", jo.getString("nonceStr"));
    jsonObject.put("paySign", jo.getString("paySign"));

    //获取微信AccessToken
    String response = restTemplate.getForObject(
        WX_ACCESS_TOKEN, String.class, wxAccount.getWxappId(), wxAccount.getAppsecret());
    JSONObject ac = JSON.parseObject(response);

    if (ac.containsKey("access_token")) {
      String accessToken = ac.getString("access_token"); //获取微信access_token

      //获取jsapi_ticket
      String resp = restTemplate.getForObject(WX_JSAPI_TICKET, String.class, accessToken);
      JSONObject ticketJson = JSON.parseObject(resp);
      if (ticketJson.containsKey("ticket")) {

        String ticket = ticketJson.getString("ticket");

        jsonObject.put("jsapi_ticket", ticket);

        Map<String, Object> signParams = new HashMap<>();
        signParams.put("jsapi_ticket", ticket);
        signParams.put("timestamp", jo.getString("timeStamp"));
        signParams.put("url", sb.toString());
        signParams.put("nonceStr", jo.getString("nonceStr"));

        jsonObject.put("signature", WxUtils.buildSha1Sign(signParams));
      }
    }

    return jsonObject;
  }

  /**
   * 进行支付.
   * @param appKey 系统key
   * @param orderId 订单id
   * @param payType 支付类型
   * @return Object
   */
  @RequestMapping(value = "doPay", method = RequestMethod.POST)
  public Object doPay(
      @RequestParam("appkey") String appKey,
      @RequestParam("orderId") Long orderId,
      @RequestParam("payType") String payType) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return daijiaApi.finishTaskErrandV4(wxApplication.getAddress(), orderId, payType, "passenger");

  }

  /**
   * 获取代驾订单是否已经被支付.
   * @param appKey 系统key
   * @param orderId 订单id
   * @return Object
   */
  @RequestMapping(value = "hasPayed", method = RequestMethod.GET)
  public Object hasPayed(
      @RequestParam("appkey") String appKey,
      @RequestParam("orderId") Long orderId) {

    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return daijiaApi.checkTaskErrandV4(wxApplication.getAddress(), orderId);
  }

  /**
   * 获取支付信息.
   * @param appKey 系统key
   * @param orderId 订单id
   * @return Object
   */
  @RequestMapping(value = "prepay", method = RequestMethod.GET)
  public Object prepay(
      @RequestParam("appkey") String appKey, 
      @RequestParam("orderId") Long orderId) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return daijiaApi.clientPayDataErrand(wxApplication.getAddress(), orderId);
  }

}
